using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

namespace EasyNetWork
{
    public sealed partial class EventPool<T> where T : BaseEventArgs
    {
        // private readonly GameFrameworkMultiDictionary<int, EventHandler<T>> m_EventHandlers; //多值字典先用List代替试试有什么区别
        private readonly Dictionary<int, List<EventHandler<T>>> m_EventHandlers;
        private readonly Queue<EasyEvent> m_Events;
        // private readonly Dictionary<object, LinkedListNode<EventHandler<T>>> m_CachedNodes;
        // private readonly Dictionary<object, LinkedListNode<EventHandler<T>>> m_TempNodes;
        // private readonly Dictionary<object, EventHandler<T>> m_CachedNodes;
        // private readonly Dictionary<object, EventHandler<T>> m_TempNodes;
        private readonly EventPoolMode m_EventPoolMode;
        private EventHandler<T> m_DefaultHandler;

        /// <summary>
        /// 初始化事件池的新实例
        /// </summary>
        /// <param name="mode"></param>
        public EventPool(EventPoolMode mode)
        {
            m_EventHandlers = new Dictionary<int, List<EventHandler<T>>>();
            m_Events = new Queue<EasyEvent>();
            // m_CachedNodes = new Dictionary<object, LinkedListNode<EventHandler<T>>>();
            // m_TempNodes = new Dictionary<object, LinkedListNode<EventHandler<T>>>();
            // m_CachedNodes = new Dictionary<object, EventHandler<T>>();
            // m_TempNodes = new Dictionary<object, EventHandler<T>>();
            m_EventPoolMode = mode;
            m_DefaultHandler = null;
        }
        
        /// <summary>
        /// 获取事件处理函数的数量
        /// </summary>
        public int EventHandlerCount
        {
            get
            {
                return m_EventHandlers.Count;
            }
        }
        
        /// <summary>
        /// 获取事件数量
        /// </summary>
        public int EventCount
        {
            get
            {
                return m_Events.Count;
            }
        }
        
        /// <summary>
        /// 事件池轮询
        /// </summary>
        public void Update()
        {
            lock (m_Events)
            {
                while (m_Events.Count > 0)
                {
                    EasyEvent eventNode = m_Events.Dequeue();
                    HandleEvent(eventNode.Sender, eventNode.EventArgs);
                }
            }
        }

        /// <summary>
        /// 关闭并清理事件池
        /// </summary>
        public void ShutDown()
        {
            Clear();
            m_EventHandlers.Clear();
            m_DefaultHandler = null;
        }
        
        /// <summary>
        /// 清理事件
        /// </summary>
        public void Clear()
        {
            lock (m_Events)
            {
                m_Events.Clear();
            }
        }

        /// <summary>
        /// 获取事件处理函数的数量
        /// </summary>
        /// <returns></returns>
        public int Count(int id)
        {
            List<EventHandler<T>> range = default(List<EventHandler<T>>);
            if (m_EventHandlers.TryGetValue(id, out range))
            {
                return range.Count;
            }

            return 0;
        }
        
        /// <summary>
        /// 检查是否存在事件处理函数
        /// </summary>
        /// <returns></returns>
        public bool Check(int id,EventHandler<T> handler)
        {
            if (handler == null)
            {
                throw new System.Exception("EventHandler无效");
            }

            List<EventHandler<T>> range = new List<EventHandler<T>>();
            if(m_EventHandlers.TryGetValue(id,out range))
            {
                
            }
            
            return range.Contains(handler);
        }
        
        /// <summary>
        /// 订阅事件处理函数
        /// </summary>
        /// <param name="id"></param>
        /// <param name="handler"></param>
        public void Subscribe(int id,EventHandler<T> handler)
        {
            if (handler == null)
            {
                throw new System.Exception("EventHandler无效");
            }

            if (!m_EventHandlers.ContainsKey(id))
            {
                m_EventHandlers[id].Add(handler);
            }
            else if((m_EventPoolMode & EventPoolMode.AllowMutiHandler) != EventPoolMode.AllowMutiHandler) //存在AllowMutiHandler且
            {
                throw new System.Exception($"EventId:{id}不支持多个处理函数");
            }
            else if ((m_EventPoolMode & EventPoolMode.AllowDuplicateHandler) != EventPoolMode.AllowDuplicateHandler && Check(id,handler))
            {
                throw new System.Exception($"EventId:{id}不存在重复的处理函数");
            }
            else
            {
                List<EventHandler<T>> eventHandlers = new List<EventHandler<T>>();
                eventHandlers.Add(handler);
                m_EventHandlers.Add(id,eventHandlers);
            }
        }
        
        /// <summary>
        /// 取消订阅事件处理函数
        /// </summary>
        public void Unsubscribe(int id,EventHandler<T> handler)
        {
            if (handler == null)
            {
                throw new System.Exception("EventHandler无效");
            }

            m_EventHandlers[id].Remove(handler);
        }
        
        /// <summary>
        /// 设置默认事件处理函数
        /// </summary>
        public void SerDefaultHandler(EventHandler<T> handler)
        {
            m_DefaultHandler = handler;
        }
        
        /// <summary>
        /// 抛出事件，这个操作是线程安全的，即使不在主线程中抛出，也可以保证主线程中回调事件处理函数，但事件会在抛出后的下一帧触发
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void Fire(object sender,T e)
        {
            if (e == null)
            {
                throw new System.Exception("事件无效");
            }

            EasyEvent eventmode = EasyEvent.Create(sender, e);
            lock (m_Events)
            {
                m_Events.Enqueue(eventmode);
            }
        }
        
        /// <summary>
        /// 抛出事件立即模式，这个操作不是线程安全的，事件会立刻分发。
        /// </summary>
        /// <param name="sender">事件源。</param>
        /// <param name="e">事件参数。</param>
        public void FireNow(object sender, T e)
        {
            if (e == null)
            {
                throw new System.Exception("事件无效");
            }

            HandleEvent(sender, e);
        }

        private void HandleEvent(object sender, T e)
        {
            bool noHandlerException = false;
            List<EventHandler<T>> range = new List<EventHandler<T>>();
            if (m_EventHandlers.TryGetValue(e.Id, out range))
            {
                for (int i = 0; i < range.Count; i++)
                {
                    range[i](sender, e);
                }
            }
            else if(m_DefaultHandler != null)
            {
                m_DefaultHandler(sender, e);
            }
            else if((m_EventPoolMode & EventPoolMode.AllowNoHandler) == 0)
            {
                noHandlerException = true;
            }

            if (noHandlerException)
            {
                throw new System.Exception($"事件Id{e.Id}没有处理函数");
            }
        }
        
        
    }

}
